package com.zlk.algorithm.dataStructure.tree.treeDp;

import com.zlk.algorithm.dataStructure.tree.TreeNode;
import org.junit.Test;

/**
 * @program: algorithm
 * @ClassName IsBalanced
 * @description: 是否是平衡二叉树
 * @author: slfang
 * @create: 2024-02-18 21:11
 * @Version 1.0
 **/
public class IsBalanced {
    //可能性
    // 信息  是否平衡  高度
    class Info{
        boolean isBalance;
        int height;

        public Info(boolean isBalance,int height){
            this.height = height;
            this.isBalance = isBalance;
        }
    }

    public  boolean isBalanced1(TreeNode head) {
        boolean[] ans = new boolean[1];
        ans[0] = true;
        process1(head, ans);
        return ans[0];
    }

    public  int process1(TreeNode head, boolean[] ans) {
        if (!ans[0] || head == null) {
            return -1;
        }
        int leftHeight = process1(head.left, ans);
        int rightHeight = process1(head.right, ans);
        if (Math.abs(leftHeight - rightHeight) > 1) {
            ans[0] = false;
        }
        return Math.max(leftHeight, rightHeight) + 1;
    }

    public boolean showProcess(TreeNode x){
        return process(x).isBalance;
    }

    public Info process(TreeNode x){
        if(x==null){
            return new Info(true,0);
        }
        Info leftInfo = process(x.left);
        Info rightInfo = process(x.right);

        boolean isBalance = true;
        int height = 1;
        int leftHeight = leftInfo.height;
        int rightHeight= rightInfo.height;
        if(!rightInfo.isBalance||!leftInfo.isBalance||Math.abs(leftHeight-rightHeight)>1){
            isBalance = false;
        }
        height += Math.max(leftHeight,rightHeight);
        return new Info(isBalance,height);
    }

    // for test
    public static TreeNode generateRandomBST(int maxLevel, int maxValue) {
        return generate(1, maxLevel, maxValue);
    }

    // for test
    public static TreeNode generate(int level, int maxLevel, int maxValue) {
        if (level > maxLevel || Math.random() < 0.5) {
            return null;
        }
        TreeNode head = new TreeNode((int) (Math.random() * maxValue));
        head.left = generate(level + 1, maxLevel, maxValue);
        head.right = generate(level + 1, maxLevel, maxValue);
        return head;
    }

    @Test
    public void test(){
        int maxLevel = 5;
        int maxValue = 100;
        int testTimes = 1000000;
        for (int i = 0; i < testTimes; i++) {
            TreeNode head = generateRandomBST(maxLevel, maxValue);
            if (isBalanced1(head) != showProcess(head)) {
                System.out.println("Oops!");
            }
        }
        System.out.println("finish!");
    }
}
